package org.zebra.mybatis.plus.core;

import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.yulichang.query.MPJQueryWrapper;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.DeleteJoinWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.github.yulichang.wrapper.UpdateJoinWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import javax.annotation.PostConstruct;

/**
 * 加强服务实现
 *
 * @param <M> mapper
 * @param <T> 实体类型
 * @author zhanghongbin
 */
@SuppressWarnings("unchecked")
public abstract class ServicePlusImpl<M extends MapperPlus<T>, T> {

    @Autowired
    private PlatformTransactionManager transactionManager;

    IServicePlus<M, T> servicePlus;

    @PostConstruct
    void initServicePlusImpl() {
        Class<T> entityClass = (Class<T>) ClassUtil.getTypeArgument(getClass(), 1);
        Class<?> mapperClass = ClassUtil.getTypeArgument(getClass(), 0);
        MapperPlus<M> mapperPlus = (MapperPlus) SpringUtil.getBean(mapperClass);
        servicePlus = new IServicePlus();
        ReflectUtil.setFieldValue(servicePlus, "baseMapper", mapperPlus);
        ReflectUtil.setFieldValue(servicePlus, "entityClass", entityClass);
        ReflectUtil.setFieldValue(servicePlus, "mapperClass", mapperClass);
    }

    public IServicePlus<M, T> getServicePlus() {
        return this.servicePlus;
    }

    public Class<T> getEntityClass() {
        return this.servicePlus.getEntityClass();
    }

    /**
     * 手动事务
     *
     * @param runnable 线程对象
     * @return true,false
     */
    protected final boolean transactional(Runnable runnable) {
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 新发起一个事务
        TransactionStatus status = transactionManager.getTransaction(def); // 获得事务状态
        try {
            runnable.run();
            // 手动提交事务
            transactionManager.commit(status);
        } catch (Exception e) {
            // 手动回滚事务
            transactionManager.rollback(status);
            return false;
        }
        return true;
    }

    protected final QueryWrapper<T> queryWrapper() {
        return Wrappers.query(this.servicePlus.getEntityClass());
    }

    protected final UpdateWrapper<T> updateWrapper() {
        return Wrappers.update();
    }

    protected final LambdaQueryWrapper<T> lambdaQueryWrapper() {
        return Wrappers.lambdaQuery(this.servicePlus.getEntityClass());
    }

    protected final LambdaUpdateWrapper<T> lambdaUpdateWrapper() {
        return Wrappers.lambdaUpdate(this.servicePlus.getEntityClass());
    }

    protected final MPJLambdaWrapper<T> mpjLambdaQueryWrapper() {
        return JoinWrappers.lambda(this.servicePlus.getEntityClass());
    }

    protected final MPJQueryWrapper<T> mpjQueryWrapper() {
        return JoinWrappers.query(this.servicePlus.getEntityClass());
    }

    protected final UpdateJoinWrapper<T> mpjUpdateWrapper() {
        return JoinWrappers.update(this.servicePlus.getEntityClass());
    }

    protected final DeleteJoinWrapper<T> mpjDeleteWrapper() {
        return JoinWrappers.delete(this.servicePlus.getEntityClass());
    }
}
